# 评测机接收程序并编译运行,然后返回
from os import system,getenv,remove
from os import path as ospath
from json import dumps, loads
from sys import path as spath
from configparser import ConfigParser
from socket import socket, gethostbyname, gethostname


def log(strr):
    print(strr, end='')


def done():
    print('#done')


def startupserver():
    '''向服务器发送一条信息
    '你的端口号' -> port
    port > 0 服务器将你加入评测机队列
    port < 0 服务器将你移出评测机队列(未完成)
    '''
    #log('making ConfigParser object...')
    config = ConfigParser()
    #done()

    #log('reading ini')
    config.read(spath[0]+'\\compile.ini')
    ip = config.get('ip', 'serverip')
    #print(ip)
    #done()

    #log('reading ini')
    port = config.get('myip', 'myport')
    #done()

    #log('Making Socket object')
    sk = socket()
    #done()

    #log('connecting...')
    while(1) :
        try :
            sk.connect((ip, 12344))
            break
        except ConnectionRefusedError:
            print('server is now unconnectable')
            continue
    print('connected server')
    #done()

    #log('sending...')
    sk.send(bytes(port, encoding='utf-8'))
    #done()

def checkout(num, pid):
    '''
    ### 比对输出与答案是否一致
    比对方式:去掉行末空格,文末回车的全文比对.
    输入:测试点编号
    '''
    check1 = open(spath[0]+'\\programout.out', 'r', encoding='utf-8')
    check2 = open(getenv('AutoCompile')+pid+'\\' +
                  str(num)+'.out', 'r', encoding='utf-8')

    read1 = ''
    read2 = ''
    while True:
        read1 = check1.readline().strip()
        read2 = check2.readline().strip()
        if read1 != read2:
            return False
        if read1 == '':
            break
    return True

def compile():
    '''将根目录下code.cpp编译为code.exe
        编译错误,返回None,否则返回1
    '''
    try :
        remove(spath[0]+'\\code.exe')
    except OSError :
        None
    system('g++ '+spath[0]+'\\code.cpp -o '+spath[0]+'\\code.exe -w')
    print('g++ '+spath[0]+'\\code.cpp -o '+spath[0]+'\\code.exe -w')
    if ospath.exists(spath[0]+'\\code.exe') :
        return 1
    return None

def check(pid):
    '''
    # 真正的评测!!!!!
    返回{'stat':'AC/WA' , 'all':总个数 , 'right':正确个数}
    '''
    rightpoint = 0
    # if ospath.exists(spath[0]+'\\point\\'+pid) :#如果存在评测数据点目录

    #log('getting point num...')
    num = 0
    
    config = ConfigParser()
    #done()
    #log('reading ini')
    config.read(getenv('AutoCompile')+pid+'\inf.ini')
    num = config.get('point', 'pointnum')

    #done()
    print('num is', str(num))

    base_path = getenv('AutoCompile')+pid+'\\'
    for i in range(int(num)):
        system(spath[0]+'\\code.exe <'+(base_path+str(i+1)+'.in')+'>'+spath[0]+'\\programout.out')
        print( spath[0]+'\\code.exe <'+(base_path+str(i+1)+'.in')+'>'+spath[0]+'\\programout.out')
        if checkout(i+1, pid) == 1:
            rightpoint = rightpoint + 1
    if str(num) == str(rightpoint) :
        return {'stat':'AC','all': str(num), 'right': str(rightpoint)}
    return {'stat':'WA','all': str(num), 'right': str(rightpoint)}

def accept():
    '''
    获取编译指令
    '''
    #log('creating object...')
    sk = socket()
    #done()

    #log('making ConfigParser object...')
    config = ConfigParser()
    #done()

    #log('reading ini')
    config.read(spath[0]+'\\compile.ini')
    port = config.get('myip', 'myport')
    #done()

    #log('getting address...')
    address = (gethostbyname(gethostname()), int(port))
    #done()
    print('address=', address)

    #log('binding...')
    sk.bind(address)
    #done()

    #log('set listen to 128...')
    sk.listen(128)
    #done()

    print('listening...')

    conn, addr = sk.accept()

    data = conn.recv(4096)
    print('get message=', data)
    f = open(spath[0]+'\\code.cpp', 'w', encoding='utf-8')
    dat = loads(str(data, encoding='utf-8'))
    f.write(dat['code'])
    f.close()

    pid = dat['pid']

    compile_stat = compile()

    dic = {}
    if compile_stat == None :
        dic = {
            'stat' : 'CE',
            'all' : '0',
            'right' : '0'
        }
    else :
        dic = check(pid)

    str_dic = dumps(dic)
    print(str_dic)

    

    print('sending result back to server.')
    config = ConfigParser()
    config.read(spath[0]+'\\compile.ini')
    ip = config.get('ip', 'serverip')
    sk = socket()
    while 1:
        try :
            sk.connect((ip, 12343))
            break
        except ConnectionRefusedError :
            print('retrying')
    sk.send(bytes(str_dic, encoding='utf-8'))


if __name__ == '__main__':
    while True:
        startupserver()
        accept()
